"""
Case Type   : dsscmd交互式
Case Name   : 交互式模式下，
Create At   : 2024/10
Owner       : haomeng
Description :
    1、构造交互节点failover异常
    2、进入交互模式，执行部分操作命令
    3、拉起恢复异常节点
    4、进入交互模式，执行部分操作命令
    5、进入交互式后，执行部分操作命令，同步进行节点间的切换
    6、恢复环境
Expect      :
    1、节点异常被踢出
    2、执行失败，Failed to get uds connection
    3、拉起恢复节点正常
    4、执行操作成功
    5、节点切换成功，交互式内执行操作命令成功
    6、恢复环境初始状态成功
History     :
"""


import os
import unittest

from testcase.utils.Logger import Logger
from testcase.utils.ComThread import ComThread
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Common import Common
from testcase.utils.Constant import Constant
from yat.test import Node
from yat.test import macro


class DsscmdInteractive(unittest.TestCase):

    def setUp(self):
        self.log = Logger()
        self.log.info(f'----{os.path.basename(__file__)} start----')
        self.node = Node('PrimaryDbUser')
        self.pri_sh = CommonSH('PrimaryDbUser')
        self.com = Common()
        self.constant = Constant()
        self.directory = 'dsscmd_file'
        self.file = 'file.txt'
        self.new_file1 = 'new_file1.txt'
        self.new_file2 = 'new_file2.txt'

    def test_dsscmd(self):
        text = '-----step1:构造交互节点failover异常  expect:节点被踢出-----'
        self.log.info(text)

        for i in range(6):
            dn_pid = self.com.get_pid(self.node, 'bin/gaussdb')
            self.log.info(dn_pid)
            kill_res = self.node.sh(f'kill -9 {dn_pid}').result()
            self.log.info(kill_res)
            self.assertNotIn('', kill_res, 'kill掉dn进程失败')
            time.sleep(6)

        status = self.pri_sh.exec_cm_ctl('query', '-Cv')
        self.log.info(status)
        self.assertIn('P Down', status.splitlines()[-1].split('|')[0], '集群状态异常')

        text = '-----step2:进入交互式模式，执行部分操作   expect:失败，Failed to get uds connection-----'
        self.log.info(text)

        param_list1 = [f'mkdir -p +data -d {self.directory}',
                       f'ls -p +data/{self.directory}',
                       f'touch -p +data/{self.directory}/{self.file}',
                       f'ls -p +data/{self.directory}/{self.file}',
                       f'find -p +data -n {self.file}',
                       f'rmdir -p +data/{self.directory} -r']
        cmd = f'''dsscmd -i'''

        execute_cmd1 = f'''source {macro.DB_ENV_PATH};
                             expect <<EOF
                             set timeout 3
                             spawn {cmd}
                             expect "dsscmd>"
                             send "{param_list1[0]}\\n"
                             expect "dsscmd>"
                             send "{param_list1[1]}\\n"
                             expect "dsscmd>"
                             send "{param_list1[2]}\\n"
                             expect "dsscmd>"
                             send "{param_list1[3]}\\n"
                             expect "dsscmd>"
                             send "{param_list1[4]}\\n"
                             expect "dsscmd>"
                             send "{param_list1[5]}\\n"
                             expect "dsscmd>"
                             send "exit\\n"
                             expect eof\n''' + '''EOF'''
        self.log.info(execute_cmd1)
        res1 = self.node.sh(execute_cmd1).result()
        self.log.info(res1)
        self.assertEqual(6, res1.count('Failed to get uds connection'), '操作命令执行成功')

        text = '-----step3:恢复交互节点dssserver进程正常   expect:恢复成功-----'
        self.log.info(text)

        start_node = self.pri_sh.exec_cm_ctl('start -n 1')
        self.log.info(start_node)
        self.assertIn(self.constant.cm_start_node_success_msg, start_node, '恢复节点失败')
        switch_a = self.pri_sh.exec_cm_ctl('switchover', '-a')
        self.log.info(switch_a)
        self.assertIn(self.constant.cm_switchover_success_msg, switch_a, '切换失败')
        time.sleep(10)

        text = '-----step4:进入交互式模式，执行部分操作   expect:执行成功-----'
        self.log.info(text)

        for param in param_list1:
            execute_cmd2 = f'''source {macro.DB_ENV_PATH};
                         expect <<EOF
                         set timeout 3
                         spawn {cmd}
                         expect "dsscmd>"
                         send "{param}\\n"
                         expect "dsscmd>"
                         send "exit\\n"
                         expect eof\n''' + '''EOF'''
            self.log.info(execute_cmd2)
            res2 = self.node.sh(execute_cmd2).result()
            self.log.info(res2)
            self.assertNotIn('Failed to get uds connection', res2, '连接dss失败')

        text = '-----step5:进入交互式后，执行部分操作命令，同步进行节点间的切换  expect:节点切换成功，交互式内执行操作命令成功-----'
        self.log.info(text)

        execute_cmd3 = f'''source {macro.DB_ENV_PATH};
                         expect <<EOF
                         set timeout 3
                         spawn {cmd}
                         expect "dsscmd>"
                         send "{param_list1[0]}\\n"
                         expect "dsscmd>"
                         send "{param_list1[1]}\\n"
                         expect "dsscmd>"
                         send "{param_list1[2]}\\n"
                         expect "dsscmd>"
                         send "{param_list1[3]}\\n"
                         expect "dsscmd>"
                         send "{param_list1[4]}\\n"
                         expect "dsscmd>"
                         send "{param_list1[5]}\\n"
                         expect "dsscmd>"
                         send "exit\\n"
                         expect eof\n''' + '''EOF'''

        dsscmd_1 = ComThread(self.com.get_sh_result,
                             args=(self.node, execute_cmd3,))
        dsscmd_1.setDaemon(True)
        dsscmd_1.start()

        switchover = ComThread(self.pri_sh.exec_cm_ctl,
                               args=('switchover', f'-n 2 -D {macro.DB_INSTANCE_PATH}'))
        switchover.setDaemon(True)
        switchover.start()

        dsscmd_1.join()
        dsscmd_1_res = dsscmd_1.get_result()
        self.log.info(dsscmd_1_res)
        switchover.join()
        switchover_res = switchover.get_result()
        self.log.info(switchover_res)
        self.assertNotIn('Failed to get uds connection', dsscmd_1_res, '连接dss失败')
        self.assertIn(self.constant.cm_switchover_success_msg, switchover_res, '切换失败')

    def tearDown(self):
        text = '-----step6:恢复环境  expect:恢复环境成功-----'
        self.log.info(text)

        status = self.pri_sh.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        p_status = status.splitlines()[-1].split('|')[0].split('6001')[-1]
        if 'Primary' in p_status and "cluster_state   : Normal" in status:
            self.log.info('---集群状态正常，无需恢复为初始状态---')
        else:
            recovery = self.pri_sh.exec_cm_ctl(mode='switchover', param='-a')
            self.log.info(recovery)

            self.assertIn(self.constant.cm_switchover_success_msg, recovery,
                          '执行失败' + text)

        status = self.pri_sh.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)

        self.assertIn('cluster_state   : Normal', status, '执行失败' + text)
        self.assertIn('P Primary Normal',
                      status.splitlines()[-1].split('|')[0].split('6001')[-1],
                      '执行失败' + text)
        self.assertIn('S Standby Normal',
                      status.splitlines()[-1].split('|')[1].split('6002')[-1],
                      '执行失败' + text)
        self.log.info(f'----{os.path.basename(__file__)} end----')
